package cn.itcast.hiss.process.activiti.multilnstance;

import cn.itcast.hiss.common.SystemConstant;
import org.activiti.bpmn.model.*;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.ExecutionEntityManager;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntityManager;
import org.activiti.engine.task.Task;

import java.util.List;

public class AddMultiInstanceExecutionCmd implements Command {

    private Process mainProcess;
    private String userId;
    private Task task;

    public AddMultiInstanceExecutionCmd(Task task, String userId, Process mainProcess){
        this.task = task;
        this.userId = userId;
        this.mainProcess = mainProcess;
    }

    @Override
    public Object execute(CommandContext commandContext) {
        // 修改变量：总量、激活、集合
        TaskEntityManager taskEntityManager = commandContext.getTaskEntityManager();
        TaskEntity taskEntity = taskEntityManager.findById(task.getId());
        // nrOfInstances 总量
        Integer nrOfInstances = Integer.valueOf(""+taskEntity.getVariable(SystemConstant.MULTILINSTANCE_NUMBER_OF_INSTANCES));
        nrOfInstances+=1;
        taskEntity.setVariable(SystemConstant.MULTILINSTANCE_NUMBER_OF_INSTANCES,nrOfInstances);
        // 激活
        Integer nrOfActiveInstances = Integer.valueOf(""+taskEntity.getVariable(SystemConstant.MULTILINSTANCE_NUMBER_OF_ACTIVE));
        nrOfActiveInstances+=1;
        taskEntity.setVariable(SystemConstant.MULTILINSTANCE_NUMBER_OF_ACTIVE,nrOfActiveInstances);
        // 集合
        List<String> userList = (List<String>) taskEntity.getVariable(SystemConstant.MULTILINSTANCE_ASSIGNEE_LIST);
        userList.add(this.userId);
        taskEntity.setVariable(SystemConstant.MULTILINSTANCE_ASSIGNEE_LIST,userList);

        // 添加节点
        // 1、找到多实例的根
        ExecutionEntity execution = taskEntity.getExecution();
        // 2、为其创建子节点
        ExecutionEntity rootExecution = getMultiInstanceRootExecution(execution);
        // 3、流转到创建的子节点
        ExecutionEntityManager executionEntityManager = commandContext.getExecutionEntityManager();
        if(rootExecution!=null){
            ExecutionEntity childExecution = executionEntityManager.createChildExecution(rootExecution);
            childExecution.setActive(true);
            childExecution.setScope(false);
            //  给新增的Execution添加变量
            // 1.1 拿xml中的流程变量的元素应用变量名
            UserTask userTask = (UserTask) mainProcess.getFlowElement(task.getTaskDefinitionKey());
            MultiInstanceLoopCharacteristics loopCharacteristics = userTask.getLoopCharacteristics();// 获取xml中配置的多实例信息
            String elementVariable = loopCharacteristics.getElementVariable();// 得到xml中配置的user
            // 绑定xml中节点元素
            childExecution.setCurrentFlowElement(userTask);
            // 2.2 添加变量，只能使用给当前execution添加变量的方法setVariableLocal
            childExecution.setVariableLocal(elementVariable,this.userId);
            childExecution.setVariableLocal(elementVariable+"Index",userList.size());
            commandContext.getAgenda().planContinueProcessOperation(childExecution);// 让流程流转到新增的节点
        }

        return null;
    }

    /**
     * 递归查找当前多实例Execution的父Execution信息
     * @param executionEntity
     * @return
     */
    public  ExecutionEntity getMultiInstanceRootExecution(ExecutionEntity executionEntity){
        ExecutionEntity parent = executionEntity.getParent();
        if(parent!=null){
            if(parent.isMultiInstanceRoot()){
                return parent;
            }else{
                return getMultiInstanceRootExecution(parent);
            }
        }
        return null;
    }

}